package cn.ihna.demo.algorithm.rbtree;

import java.util.LinkedList;

/**
 * @author xianyingda@gmail.com
 * @serial
 * @since 2020-08-29 08:07
 */
public class RBTree<K extends Comparable<K>, V> {

    public static final boolean RED = true;
    public static final boolean BLACK = false;

    public void print() {
        LinkedList<Node> linkedList = new LinkedList<>();
        linkedList.addLast(root);
        print(linkedList);
    }

    private void print(LinkedList<Node> list) {
        if (list == null || list.size() == 0) {
            return;
        }
        LinkedList<Node> next = new LinkedList<>();
        for (Node node : list) {
            System.out.print(node.key + "(" + (isRed(node) ? "r" : "b") + ") ");
            if (node.left != null) {
                next.addLast(node.left);
            }
            if (node.right != null) {
                next.addLast(node.right);
            }
        }
        System.out.println();
        print(next);
    }

    private class Node {
        public K key;
        public V value;
        public Node left, right;
        public boolean color;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
            this.color = RED; // 默认创建的节点是红色的 因为添加的节点都是要和叶子节点进行融合 黑色的节点都是分裂出来的
        }
    }

    private Node root;
    private int size = 0;

    // 红黑树左旋 旋转过程中并不保证红黑树性质
    private Node leftRotate(Node node) {
        Node x = node.right;
        node.right = x.left;
        x.left = node;
        // 颜色
        x.color = node.color;
        node.color = RED;
        return x;
    }

    // 红黑树右旋
    private Node rightRotate(Node node) {
        Node x = node.left;
        node.left = x.right;
        x.right = node;
        // 颜色
        x.color = node.color;
        node.color = RED;
        return x;
    }


    private void flipColors(Node node) {
        // 颜色翻转
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }

    private boolean isRed(Node node) {
        if (node == null) {
            return BLACK;
        }
        return node.color;
    }

    // 向红黑树中添加新的元素
    public void add(K key, V value) {
        root = add(root, key, value);
        root.color = BLACK;
    }

    public V get(K key) {
        return getValue(key, root);
    }

    private V getValue(K key, Node node) {
        if (node == null) {
            return null;
        }
        if (key.compareTo(node.key) == 0) {
            return node.value;
        } else if (key.compareTo(node.key) > 0) {
            return getValue(key, node.right);
        } else {
            return getValue(key, node.left);
        }
    }

    public int size() {
        return this.size;
    }

    private Node add(Node node, K key, V value) {
        if (node == null) {
            size++;
            return new Node(key, value); // 默认插入红色节点
        }
        if (key.compareTo(node.key) < 0) {
            node.left = add(node.left, key, value);
        } else {
            node.right = add(node.right, key, value);
        }

        if (isRed(node.right) && !isRed(node.left)) {
            node = leftRotate(node);
            System.out.println("我已左旋");
        }
        if (isRed(node.left) && isRed(node.left.left)) {
            node = rightRotate(node);
            System.out.println("我已右旋");
        }
        if (isRed(node.left) && isRed(node.right)) {
            flipColors(node);
            System.out.println("我已翻转");
        }

        return node;
    }

}
